package com.up4years.aspect;

import java.util.Arrays;
import java.util.Map;

import javax.annotation.Resource;

import org.apache.log4j.Logger;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.core.Ordered;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.danga.MemCached.MemCachedClient;
import com.up4years.utils.EncryptUtil;
/**
 * 启用缓存 先于事务执行
 * @author Administrator
 *
 */
@Aspect
@Component
public class MemcachedAspect implements Ordered{
	Logger logger = Logger.getLogger(MemcachedAspect.class); 
 	
	private MemCachedClient memCachedClient;
	@Resource
	public void setMemCachedClient(MemCachedClient memCachedClient) {
		this.memCachedClient = memCachedClient;
	}
	
	/**拦截CachedBaseManager查询方法**/
	@Pointcut(value="execution(* query*(..)) &&target(com.up4years.dataapi.service.base.CachedBaseManager) && args(statementName,parameters)")
	private void queryMethod1(String statementName, Map<String, Object> parameters){}
	@Pointcut(value="execution(* get*(..))&&target(com.up4years.dataapi.service.base.CachedBaseManager) && args(statementName,parameters)")
	private void getMethod1(String statementName, Map<String, Object> parameters){}
	
	
	/**拦截CachedBaseManager查询方法**/
	@Pointcut(value="execution(* query*(..))&&target(com.up4years.dataapi.service.base.CachedBaseManager) && args(entity,id)")
	private void queryMethod2(Class<?> entity, Long id){}
	@Pointcut(value="execution(* get*(..))&&target(com.up4years.dataapi.service.base.CachedBaseManager) && args(entity,id)")
	private void getMethod2(Class<?> entity, Long id){}
	
	/**拦截CachedBaseManager查询方法**/
	@Pointcut(value="execution(* query*(..))&&target(com.up4years.dataapi.service.base.CachedBaseManager) && args(statementName,args)")
	private void queryMethod3(String statementName, Object[] args){}
	
	/**拦截CachedBaseManager查询方法**/
	@Pointcut(value="execution(* queryByObj*(..))&&target(com.up4years.dataapi.service.base.CachedBaseManager) && args(statementName,obj)")
	private void queryMethod4(String statementName, Object obj){}
	
	/**拦截CachedBaseManager查询方法**/
	@Pointcut("queryMethod1(statementName,parameters) || getMethod1(statementName,parameters)")
	private void search1(String statementName, Map<String, Object> parameters){}
	@Pointcut("queryMethod2(entity,id) || getMethod2(entity,id)")
	private void search2(Class<?> entity, Long id){}
	
	/**拦截所有查询方法 先从MemCached读取 无值再查询数据库**/
	@Around("search2(entity,id)")
	public Object aroundDao1(ProceedingJoinPoint proceedingJoinPoint,Class<?> entity, Long id) throws Throwable{
		logger.debug("开始查询数据\t"+entity.getCanonicalName()+"\t"+id);
 		String key = EncryptUtil.MD5Encode(entity.getCanonicalName()+id);
 		 
 		Object value = this.memCachedClient.get(key);
 		if(value==null){
 			logger.debug("未从MemCached读取数据，从DB查询");
 			value = proceedingJoinPoint.proceed();
			logger.debug("将从DB查询到的数据存至MemCached");
			this.memCachedClient.set(key, value);		
 			return value;
 		}else{
 			logger.debug("从MemCached读取到数据，返回");
 			return value;
 		}
 		
	}
	/**拦截所有查询方法 先从MemCached读取 无值再查询数据库**/
	@Around("search1(statementName,parameters)")
	public Object aroundDao2(ProceedingJoinPoint proceedingJoinPoint,String statementName, Map<String, Object> parameters) throws Throwable{
		logger.debug("开始查询数据\t"+statementName);
		String key = EncryptUtil.MD5Encode(statementName+parameters.toString());
		Object value = this.memCachedClient.get(key);
		if(value==null){
 			logger.debug("未从MemCached读取数据，从DB查询");
 			value = proceedingJoinPoint.proceed();
			logger.debug("将从DB查询到的数据存至MemCached");
			this.memCachedClient.set(key, value);		
 			return value;
 		}else{
			logger.debug("从MemCached读取到数据，返回");
			return value;
		}
	}
	/**拦截所有查询方法 先从MemCached读取 无值再查询数据库**/
	@Around("queryMethod3(statementName,args)")
	public Object aroundDao3(ProceedingJoinPoint proceedingJoinPoint,String statementName, Object[] args) throws Throwable{
		logger.debug("开始查询数据\t"+statementName);
		String key = EncryptUtil.MD5Encode(statementName+Arrays.toString(args));
		Object value = this.memCachedClient.get(key);
		if(value==null){
			logger.debug("未从MemCached读取数据，从DB查询");
			value = proceedingJoinPoint.proceed();
			logger.debug("将从DB查询到的数据存至MemCached");
			this.memCachedClient.set(key, value);		
			return value;
		}else{
			logger.debug("从MemCached读取到数据，返回");
			return value;
		}
	}
	
	
	/**拦截所有查询方法 先从MemCached读取 无值再查询数据库**/
	@Around("queryMethod4(statementName,obj)")
	public Object aroundDao4(ProceedingJoinPoint proceedingJoinPoint,String statementName, Object obj) throws Throwable{
		logger.debug("开始查询数据\t"+statementName);
		String key = EncryptUtil.MD5Encode(statementName+"queryByObj"+JSON.toJSONString(obj));
		System.out.println("新加key="+key);
		Object value = this.memCachedClient.get(key);
		System.out.println("新加value="+JSON.toJSONString(value));
		if(value==null){
			logger.debug("未从MemCached读取数据，从DB查询");
			System.out.println("新加proceedingJoinPoint.proceed()="+proceedingJoinPoint.proceed());
			value = proceedingJoinPoint.proceed();
			logger.debug("将从DB查询到的数据存至MemCached");
			this.memCachedClient.set(key, value);		
			return value;
		}else{
			logger.debug("从MemCached读取到数据，返回");
			return value;
		}
		
	}

	@Override
	public int getOrder() {
 		return 0;
	}
}
